/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package ru.ssau.entities;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.ejb.CreateException;
import javax.ejb.EJBException;
import javax.ejb.EntityBean;
import javax.ejb.EntityContext;
import javax.ejb.NoSuchEntityException;
import javax.ejb.ObjectNotFoundException;
import javax.ejb.RemoveException;
import javax.naming.NamingException;
import javax.sql.DataSource;
import org.jdom.Element;
import ru.ssau.utils.XMLHelper;
import ru.ssau.utils.DatabaseUtil;


public class AuthorizationInfoBean implements EntityBean {

    private static final String REQUEST_AUTHORIZATION_INFO_ADD =
            "INSERT INTO AuthorizationInfo(AuthorizationID,UserID,Login,Pass) VALUES(?,?,?,?)";
    private static final String REQUEST_AUTHORIZATION_INFO_ID_SEQUENCE_GET_NEXT_VALUE =
            "SELECT AuthInfoIDSeq.NEXTVAL FROM dual";
    private static final String REQUEST_AUTHORIZATION_INFO_DELETE_BY_ID =
            "DELETE FROM AuthorizationInfo WHERE AuthorizationID=?";
    private static final String REQUEST_AUTHORIZATION_INFO_GET_BY_ID =
            "SELECT UserId,Login,Pass FROM AuthorizationInfo WHERE AuthorizationId=?";
    private static final String REQUEST_AUTHORIZATION_INFO_GET_BY_USER_ID =
            "SELECT AuthorizationId,Login,Pass FROM AuthorizationInfo "
            + "WHERE UserId=?";
    private static final String REQUEST_AUTHORIZATION_INFO_FIND_BY_ID =
            "SELECT AuthorizationId FROM AuthorizationInfo WHERE AuthorizationId=?";
    private static final String REQUEST_AUTHORIZATION_INFO_FIND_BY_USER_ID =
            "SELECT AuthorizationId FROM AuthorizationInfo WHERE UserId=?";
    private static final String REQUEST_AUTHORIZATION_INFO_UPDATE =
            "UPDATE AuthorizationInfo SET UserId=?, Login=?, "
            + "Pass=? WHERE AuthorizationId=?";

    private Integer id;
    private Integer userId;
    private String login;
    private String password;

    private EntityContext entityContext;
    private DataSource dataSource;

    private boolean isEdited;

    public void setEntityContext(EntityContext ctx) {
        entityContext = ctx;
        try {
            dataSource = DatabaseUtil.getDataSource();
            isEdited = false;
        } catch(NamingException ex) {
            throw new EJBException("Cannon lookup connection pool on server", ex);
        }
    }

    public void unsetEntityContext() {
        entityContext = null;
    }

    public Integer ejbCreate(Integer userId, String login, String password) throws CreateException {
        PreparedStatement idGeneratePS = null;
        PreparedStatement updatePS = null;
        Connection conn = null;
        try {
            conn = dataSource.getConnection();
            //id generation
            idGeneratePS = conn.prepareStatement(REQUEST_AUTHORIZATION_INFO_ID_SEQUENCE_GET_NEXT_VALUE);
            ResultSet rs = idGeneratePS.executeQuery();
            if(rs.next()) {
                id = rs.getInt(1);
            } else {
                throw new CreateException("Cannot generate id for thread");
            }
            updatePS = conn.prepareStatement(REQUEST_AUTHORIZATION_INFO_ADD);
            updatePS.setInt(1, id.intValue());
            updatePS.setInt(2, userId.intValue());
            updatePS.setString(3, login);
            updatePS.setString(4, password);
            if(updatePS.executeUpdate() != 1) {
                throw new CreateException("Insertion error");
            }
            this.userId = userId;
            this.login = login;
            this.password = password;
            isEdited = false;
            return id;
        } catch(SQLException ex) {
            throw new EJBException("Error in INSERT statement", ex);
        } finally {
            DatabaseUtil.closeConnection(conn, idGeneratePS);
            DatabaseUtil.closeConnection(null, updatePS);
        }
    }

    public void ejbPostCreate(Integer userId, String login, String password) throws CreateException {

    }

    public Integer ejbFindByPrimaryKey(Integer primaryKey) throws ObjectNotFoundException {
        PreparedStatement ps = null;
        Connection conn = null;
        try {
            conn = dataSource.getConnection();
            ps = conn.prepareStatement(REQUEST_AUTHORIZATION_INFO_FIND_BY_ID);
            ps.setInt(1, primaryKey.intValue());
            ResultSet rs = ps.executeQuery();
            if(!rs.next()) {
                throw new ObjectNotFoundException("No entity found by id = " + primaryKey.toString());
            }
            return primaryKey;
        } catch(SQLException ex) {
            throw new EJBException("Error in SELECT statement", ex);
        } finally {
            DatabaseUtil.closeConnection(conn, ps);
        }
    }

    public Integer ejbFindByUserId(Integer userId) throws ObjectNotFoundException {
        PreparedStatement ps = null;
        Connection conn = null;
        try {
            conn = dataSource.getConnection();
            ps = conn.prepareStatement(REQUEST_AUTHORIZATION_INFO_FIND_BY_USER_ID);
            ps.setInt(1, userId.intValue());
            ResultSet rs = ps.executeQuery();
            if(!rs.next()) {
                throw new ObjectNotFoundException("No entity found by id = " + userId.toString());
            }
            Integer key = rs.getInt(1);
            return key;
        } catch(SQLException ex) {
            throw new EJBException("Error in SELECT statement", ex);
        } finally {
            DatabaseUtil.closeConnection(conn, ps);
        }
    }
    
    public void ejbActivate() {

    }

    public void ejbPassivate() {

    }

    public void ejbLoad() {
        PreparedStatement ps = null;
        Connection conn = null;
        id = (Integer) entityContext.getPrimaryKey();
        try {
            conn = dataSource.getConnection();
            ps = conn.prepareStatement(REQUEST_AUTHORIZATION_INFO_GET_BY_ID);
            ps.setInt(1, id);
            ResultSet rs = ps.executeQuery();
            if (rs.next()) {
                userId = Integer.valueOf(rs.getInt("UserId"));
                login = rs.getString("Login");
                password = rs.getString("Pass");
            } else {
                throw new NoSuchEntityException("No entity found by id = " + id.toString());
            }
            isEdited = false;
        } catch (SQLException ex) {
            throw new EJBException("Error in SELECT statement", ex);
        } finally {
            DatabaseUtil.closeConnection(conn, ps);
        }
    }

    public void ejbStore() {
        if(!isEdited) return;
        PreparedStatement ps = null;
        Connection conn = null;
        try {
            conn = dataSource.getConnection();
            ps = conn.prepareStatement(REQUEST_AUTHORIZATION_INFO_UPDATE);
            ps.setInt(1, userId.intValue());
            ps.setString(2, login);
            ps.setString(3, password);
            ps.setInt(4, id.intValue());
            if(ps.executeUpdate() < 1) {
                throw new NoSuchEntityException("No entity found by id = " + id.toString());
            }
            isEdited = false;
        } catch(SQLException ex) {
            throw new EJBException("Error in UPDATE statement", ex);
        } finally {
            DatabaseUtil.closeConnection(conn, ps);
        }
    }

    public void ejbRemove() throws RemoveException {
        //??
        //throw new UnsupportedOperationException();
        PreparedStatement ps = null;
        Connection conn = null;
        try {
            conn = dataSource.getConnection();
            ps = conn.prepareStatement(REQUEST_AUTHORIZATION_INFO_DELETE_BY_ID);
            ps.setInt(1, id.intValue());
            if(ps.executeUpdate() < 1) {
                throw new NoSuchEntityException("No entity found by id = " + id.toString());
            }
            isEdited = false;
        } catch(SQLException ex) {
            throw new EJBException("Error in DELETE statement", ex);
        } finally {
            DatabaseUtil.closeConnection(conn, ps);
        }
    }

    public Integer getId() {
        return id;
    }

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
        isEdited = true;
    }

    public String getLogin() {
        return login;
    }

    public void setLogin(String login) {
        this.login = login;
        isEdited = true;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
        isEdited = true;
    }

    public String getStringRepresentation() {
        StringBuilder sb = new StringBuilder();
        sb.append(getClass().getName());
        sb.append(": [id=");
        sb.append(id);
        sb.append(", userId=");
        sb.append(userId);
        sb.append(", login=");
        sb.append(login);
        sb.append(", password=");
        sb.append(password);
        sb.append("]");
        return sb.toString();
    }

    public Element toXMLElement() {
        Element root = new Element("AuthorizationInfo");
        XMLHelper.addElement(root, "id", id);
        XMLHelper.addElement(root, "userId", userId);
        XMLHelper.addElement(root, "login", login);
        XMLHelper.addElement(root, "password", password);
        return root;
    }

    public void loadFromXMLElement(Element data) {
        throw new UnsupportedOperationException();
    }

}
